﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;


namespace LRSTaxServices.DAL
{
	public class TableAdapterHelper
	{
		#region Public Methods

		#region BeginTransaction

		public static SqlTransaction BeginTransaction(object tableAdapter)
		{
			return BeginTransaction(tableAdapter, IsolationLevel.ReadUncommitted);
		}


		public static SqlTransaction BeginTransaction(object tableAdapter, IsolationLevel isolationLevel)
		{
			// Get the table adapter's type.
			Type type = tableAdapter.GetType();

			// Get the connection on the adapter.
			SqlConnection connection = GetConnection(tableAdapter);

			// Make sure connection is open to start the transaction.
			if (connection.State == ConnectionState.Closed)
				connection.Open();

			// Start a transaction on the connection.
			SqlTransaction transaction = connection.BeginTransaction(isolationLevel);

			// Set the transaction on the table adapter.
			SetTransaction(tableAdapter, transaction);

			return (transaction);
		}

		#endregion

		#region GetConnection

		/// <summary>
		/// Gets the connection from the specified table adapter.
		/// </summary>
		private static SqlConnection GetConnection(object tableAdapter)
		{
			Type type = tableAdapter.GetType();
			//PropertyInfo connectionProperty = type.GetProperty("Connection", BindingFlags.NonPublic | BindingFlags.Instance);
			PropertyInfo connectionProperty = type.GetProperty("Connection", BindingFlags.Public | BindingFlags.Instance);
			SqlConnection connection = (SqlConnection)connectionProperty.GetValue(tableAdapter, null);
			return (connection);
		}

		#endregion

		#region SetConnection

		/// <summary>
		/// Sets the connection on the specified table adapter.
		/// </summary>
		private static void SetConnection(object tableAdapter, SqlConnection connection)
		{
			Type type = tableAdapter.GetType();
			//PropertyInfo connectionProperty = type.GetProperty("Connection", BindingFlags.NonPublic | BindingFlags.Instance);
			PropertyInfo connectionProperty = type.GetProperty("Connection", BindingFlags.Public | BindingFlags.Instance);
			connectionProperty.SetValue(tableAdapter, connection, null);
		}

		#endregion

		#region SetTransaction

		/// <summary>
		/// Enlists the table adapter in a transaction.
		/// </summary>
		public static void SetTransaction(object tableAdapter, SqlTransaction transaction)
		{
			// Set the table adapter's type.
			Type type = tableAdapter.GetType();

			// Set the transaction on each command in the adapter.
			//PropertyInfo commandsProperty = type.GetProperty("CommandCollection", BindingFlags.NonPublic | BindingFlags.Instance);
			//SqlCommand[] commands = (SqlCommand[])commandsProperty.GetValue(tableAdapter, null);
			//foreach (SqlCommand command in commands)
			//    command.Transaction = transaction;

			PropertyInfo adapterProperty = type.GetProperty("Adapter", BindingFlags.NonPublic | BindingFlags.Instance);

			SqlDataAdapter adapter = (SqlDataAdapter)adapterProperty.GetValue(tableAdapter, null);

			if (adapter.UpdateCommand != null)
				adapter.UpdateCommand.Transaction = transaction;

			if (adapter.InsertCommand != null)
				adapter.InsertCommand.Transaction = transaction;

			if (adapter.DeleteCommand != null)
				adapter.DeleteCommand.Transaction = transaction;

			// Set the connection on the table adapter.
			SetConnection(tableAdapter, transaction.Connection);
		}

		#endregion

		#endregion
	}
}
